// scripts/verify-fixes.js
// 专门用于验证合约修复的脚本
const { ethers } = require("hardhat");
const { time } = require("@nomicfoundation/hardhat-network-helpers");

async function main() {
    console.log("=== DeciCourt Contract Fixes Verification ===\n");
    
    // 获取账户
    const [deployer, plaintiff, defendant, juror1, juror2, juror3, juror4, juror5] = await ethers.getSigners();
    
    // 部署合约
    const JuryTokenFactory = await ethers.getContractFactory("JuryToken");
    const juryToken = await JuryTokenFactory.deploy();
    await juryToken.waitForDeployment();
    
    const DeciCourtFactory = await ethers.getContractFactory("DeciCourt");
    const deciCourt = await DeciCourtFactory.deploy(
        await juryToken.getAddress(),
        ethers.parseEther("100"), // filingFee
        ethers.parseEther("500"), // jurorStake
        3, // jurySize
        300, // commitDuration
        300, // revealDuration
        50, // penaltyRate
        5, // appealDepositMultiplier
        600, // appealDuration
        5 // appealJurySize
    );
    await deciCourt.waitForDeployment();
    
    // 分发代币和授权
    const accounts = [plaintiff, defendant, juror1, juror2, juror3, juror4, juror5];
    for (const account of accounts) {
        await juryToken.transfer(account.address, ethers.parseEther("2000"));
        await juryToken.connect(account).approve(await deciCourt.getAddress(), ethers.MaxUint256);
    }
    
    console.log("1. Testing Constructor Parameter Validation Fix");
    console.log("=" .repeat(50));
    
    try {
        // 测试无效的代币地址
        await DeciCourtFactory.deploy(
            ethers.ZeroAddress, // 无效地址
            ethers.parseEther("100"),
            ethers.parseEther("500"),
            3, 300, 300, 50, 5, 600, 5
        );
        console.log("❌ Should have rejected zero token address");
    } catch (error) {
        console.log("✅ Correctly rejected zero token address");
    }
    
    try {
        // 测试无效的惩罚率
        await DeciCourtFactory.deploy(
            await juryToken.getAddress(),
            ethers.parseEther("100"),
            ethers.parseEther("500"),
            3, 300, 300, 101, // 无效惩罚率
            5, 600, 5
        );
        console.log("❌ Should have rejected penalty rate > 100%");
    } catch (error) {
        console.log("✅ Correctly rejected penalty rate > 100%");
    }
    
    console.log("\n2. Testing Improved Juror Selection Algorithm");
    console.log("=" .repeat(50));
    
    // 注册陪审员
    await deciCourt.connect(juror1).registerAsJuror();
    await deciCourt.connect(juror2).registerAsJuror();
    await deciCourt.connect(juror3).registerAsJuror();
    await deciCourt.connect(juror4).registerAsJuror();
    await deciCourt.connect(juror5).registerAsJuror();
    
    // 创建多个案件来测试选择算法
    for (let i = 0; i < 5; i++) {
        await deciCourt.connect(plaintiff).createCase(defendant.address, `QmEvidence${i}`);
        const jurors = await deciCourt.getCaseJurors(i + 1);
        
        // 检查是否有重复陪审员
        const uniqueJurors = [...new Set(jurors)];
        if (uniqueJurors.length === jurors.length) {
            console.log(`✅ Case ${i + 1}: No duplicate jurors (${jurors.length} selected)`);
        } else {
            console.log(`❌ Case ${i + 1}: Found duplicate jurors!`);
        }
    }
    
    console.log("\n3. Testing Fixed Fund Distribution Logic");
    console.log("=" .repeat(50));
    
    const plaintiffInitialBalance = await juryToken.balanceOf(plaintiff.address);
    const defendantInitialBalance = await juryToken.balanceOf(defendant.address);
    
    // 创建案件并模拟投票（原告获胜）
    await deciCourt.connect(plaintiff).createCase(defendant.address, "QmTestFunds");
    const caseId = 6;
    const jurors = await deciCourt.getCaseJurors(caseId);
    
    // 所有陪审员投票支持原告
    const vote = 1; // ForPlaintiff
    const salts = [];
    
    for (let i = 0; i < jurors.length; i++) {
        const salt = ethers.randomBytes(32);
        salts.push(salt);
        const commitment = ethers.keccak256(ethers.solidityPacked(["uint8", "bytes32"], [vote, salt]));
        
        const jurorSigner = await ethers.getSigner(jurors[i]);
        await deciCourt.connect(jurorSigner).commitVote(caseId, commitment);
    }
    
    await time.increase(301); // 等待承诺阶段结束
    
    for (let i = 0; i < jurors.length; i++) {
        const jurorSigner = await ethers.getSigner(jurors[i]);
        await deciCourt.connect(jurorSigner).revealVote(caseId, vote, salts[i]);
    }
    
    await time.increase(301); // 等待揭示阶段结束
    await deciCourt.executeVerdict(caseId);
    
    const plaintiffFinalBalance = await juryToken.balanceOf(plaintiff.address);
    const filingFee = ethers.parseEther("100");
    
    // 原告应该收回立案费（因为获胜且没有罚金）
    if (plaintiffFinalBalance.toString() === plaintiffInitialBalance.toString()) {
        console.log("✅ Fund distribution fix working - plaintiff got filing fee back");
    } else {
        console.log("❌ Fund distribution issue detected");
        console.log(`   Expected: ${ethers.formatEther(plaintiffInitialBalance)}`);
        console.log(`   Actual: ${ethers.formatEther(plaintiffFinalBalance)}`);
    }
    
    console.log("\n4. Testing Juror Protection Mechanism");
    console.log("=" .repeat(50));
    
    // 创建案件让一个陪审员投错票
    await deciCourt.connect(plaintiff).createCase(defendant.address, "QmTestProtection");
    const protectionCaseId = 7;
    const protectionJurors = await deciCourt.getCaseJurors(protectionCaseId);
    
    const protectionSalts = [];
    for (let i = 0; i < protectionJurors.length; i++) {
        const voteOption = i === 0 ? 2 : 1; // 第一个投被告，其他投原告
        const salt = ethers.randomBytes(32);
        protectionSalts.push(salt);
        const commitment = ethers.keccak256(ethers.solidityPacked(["uint8", "bytes32"], [voteOption, salt]));
        
        const jurorSigner = await ethers.getSigner(protectionJurors[i]);
        await deciCourt.connect(jurorSigner).commitVote(protectionCaseId, commitment);
    }
    
    await time.increase(301);
    
    for (let i = 0; i < protectionJurors.length; i++) {
        const voteOption = i === 0 ? 2 : 1;
        const jurorSigner = await ethers.getSigner(protectionJurors[i]);
        await deciCourt.connect(jurorSigner).revealVote(protectionCaseId, voteOption, protectionSalts[i]);
    }
    
    await time.increase(301);
    await deciCourt.executeVerdict(protectionCaseId);
    
    // 检查投错票的陪审员是否保留了最低质押
    const wrongJurorInfo = await deciCourt.jurorsInfo(protectionJurors[0]);
    const minStake = ethers.parseEther("500") / 10n; // 10%的最低质押
    
    if (wrongJurorInfo.stakedAmount >= minStake) {
        console.log("✅ Juror protection working - minimum stake preserved");
        console.log(`   Remaining stake: ${ethers.formatEther(wrongJurorInfo.stakedAmount)} JURY`);
    } else {
        console.log("❌ Juror protection failed - stake below minimum");
    }
    
    console.log("\n5. Testing Appeal Logic Fix");
    console.log("=" .repeat(50));
    
    // 创建案件让被告获胜，然后测试上诉
    await deciCourt.connect(plaintiff).createCase(defendant.address, "QmTestAppeal");
    const appealCaseId = 8;
    const appealJurors = await deciCourt.getCaseJurors(appealCaseId);
    
    // 让被告获胜
    const appealSalts = [];
    const defendantVote = 2; // ForDefendant
    
    for (let i = 0; i < appealJurors.length; i++) {
        const salt = ethers.randomBytes(32);
        appealSalts.push(salt);
        const commitment = ethers.keccak256(ethers.solidityPacked(["uint8", "bytes32"], [defendantVote, salt]));
        
        const jurorSigner = await ethers.getSigner(appealJurors[i]);
        await deciCourt.connect(jurorSigner).commitVote(appealCaseId, commitment);
    }
    
    await time.increase(301);
    
    for (let i = 0; i < appealJurors.length; i++) {
        const jurorSigner = await ethers.getSigner(appealJurors[i]);
        await deciCourt.connect(jurorSigner).revealVote(appealCaseId, defendantVote, appealSalts[i]);
    }
    
    await time.increase(301);
    await deciCourt.executeVerdict(appealCaseId);
    
    // 原告上诉
    const plaintiffBalanceBeforeAppeal = await juryToken.balanceOf(plaintiff.address);
    await deciCourt.connect(plaintiff).appeal(appealCaseId);
    
    console.log("✅ Appeal initiated successfully");
    
    // 检查上诉后的陪审团规模
    const appealJurors2 = await deciCourt.getCaseJurors(appealCaseId);
    if (appealJurors2.length === 5) {
        console.log("✅ Appeal jury size correctly increased to 5");
    } else {
        console.log(`❌ Appeal jury size incorrect: ${appealJurors2.length}`);
    }
    
    console.log("\n=== VERIFICATION COMPLETE ===");
    console.log("All major fixes have been verified and are working correctly!");
    console.log("\nContract Addresses:");
    console.log(`JuryToken: ${await juryToken.getAddress()}`);
    console.log(`DeciCourt: ${await deciCourt.getAddress()}`);
}

main()
    .then(() => process.exit(0))
    .catch((error) => {
        console.error(error);
        process.exit(1);
    });